# Copyright 2025 The IREE Authors
#
# Licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

# A wrapper around add_custom_command and a minimal subset of Bazel genrule.
#
# Parameters:
# NAME: Name of the target.
# SRCS: Source files, including any script run in the command.
#       Unlike Bazel's genrule, we do not try to distinguish between the
#       two. The distinction is needed when tools need to be compiled for
#       host, but that doesn't concern us if we only need to run python
#       scripts.
# OUTS: Files generated by the command.
# CMD:  The command to be executed. The only supported special Bazel genrule
#       syntax is:
#            * "$(rootpath x)", only supported for source files. In conversion
#              to CMake, this expands to the path of x relatively to the current
#              source dir.
#            * "$(execpath x)", only supported for generated files. In
#              conversion to CMake, this expands to just x, as the binary dir is
#              the default working dir for custom commands anyway.
function(iree_genrule)
  cmake_parse_arguments(
    _RULE
    ""
    "NAME"
    "SRCS;OUTS;CMD"
    ${ARGN}
  )

  set(_CMD "${_RULE_CMD}")

  # Replace Bazel syntax $(rootpath x) with the path into the source dir.
  string(REGEX REPLACE "\\$\\(rootpath ([^)]+)\\)" "${CMAKE_CURRENT_SOURCE_DIR}/\\1" _CMD "${_CMD}")

  # Simply drop Bazel syntax $(execpath x) as Bazel custom commands are executed
  # by default in the build directory.
  string(REGEX REPLACE "\\$\\(execpath ([^)]+)\\)" "\\1" _CMD "${_CMD}")

  # Convert CMake/Unix-style paths with forward slashes to Windows-style with
  # backslashes. It is a bit incorrect to do it as a single cmake_path command
  # on the whole command string, which isn't technically a path, but this should
  # not matter if all what this does is this character substitution.
  # It is not worth implementing a cumbersome fix here, when CMake 4.0 brings
  # the $<PATH:NATIVE_PATH,...> generator expression which is a simpler, better
  # fix here. TODO(bjacob): use that generator expression in the above string
  # replace command directly, whenever we can rely on CMake 4.0.
  cmake_path(NATIVE_PATH _CMD _CMD)

  # CMake add_custom_command expects a list as the command, so we replace spaces
  # by semicolon here. Careful to avoid replacing backslash-escaped spaces.
  string(REGEX REPLACE "([^\\]) " "\\1;" _CMD "${_CMD}")

  add_custom_command(
    OUTPUT
      "${_RULE_OUTS}"
    COMMAND
      ${_CMD}
    DEPENDS
      "${_RULE_SRCS}"
    COMMENT
      "Generating ${_RULE_OUTS}"
    VERBATIM
  )

  add_custom_target("${_RULE_NAME}"
    DEPENDS "${_RULE_OUTS}"
  )
endfunction()
